package com.example.sturedis.factories;

import com.example.sturedis.service.StudentService;
import lombok.Data;
import org.redisson.api.RBloomFilter;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 布隆过滤器管理器
 */
@Component
@Data
public class BloomManager {

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private StudentService studentService;

    private RBloomFilter<Integer> stuBloom;

    @Autowired
    private ThreadPoolExecutor tp;

    public void init(){
        tp.execute(()->{
            //① 对布隆过滤器进行初始化
            stuBloom = redissonClient.getBloomFilter("stuBloom");
        /*
            参数一：期望向布隆过滤器中添加的值的个数
            参数二：误判的概率
         */
            stuBloom.tryInit(1000,0.01);

            //② 向布隆过滤器中存入数据库中存在的id值
            List<Integer> ids = studentService.getIds();
//        ids.forEach(id->stuBloom.add(id));
            ids.forEach(stuBloom::add);
        });
    }

    @Bean
    public ThreadPoolExecutor tp(){
        AtomicInteger threadNumber = new AtomicInteger(1);
        int coreSize = Runtime.getRuntime().availableProcessors() + 1;
        int maxSize = coreSize;
        ThreadPoolExecutor tp = new ThreadPoolExecutor(
                coreSize,
                maxSize,
                0,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(),
                r->{
                    Thread t = new Thread(Thread.currentThread().getThreadGroup(), r,
                            "cdm-" + threadNumber.getAndIncrement(),
                            0);
                    if (t.isDaemon())
                        t.setDaemon(false);
                    if (t.getPriority() != Thread.NORM_PRIORITY)
                        t.setPriority(Thread.NORM_PRIORITY);
                    return t;
                },
                new ThreadPoolExecutor.AbortPolicy()
        );

        return tp;
    }
}
